//该文件只记录creep行为活动
//
const {
    withDraw,
    pickUp,
    carryOtherCreep,
    repair,
    build,
    up,
    followFlagUpRoom, replenishBuild, replenishEnergy, toStop,
} = require("./Behavior");
const {findRoleCreeps, findBuild,findEnergyStore, findLink, findFlagList, findBestClose} = require("./Find");
const {EnumBehavior, EnumHarvestMode, EnumRole, EnumFlag, EnumReplenish} = require("./Enum");

//Harvest
module.exports.harvest = creep => {
    switch (creep.memory.behavior) {
        case EnumBehavior.Free: {
            {
                if (creep.usedStore()>creep.maxStore()*0.3) {//store have letter energy
                    if (creep.memory.bindLink) {//exist bind link
                        let bindLink = Game.getObjectById(creep.memory.bindLink);
                        if (bindLink.freeStore() > 0) {//trans link
                            creep.bestTrans(bindLink);
                            creep.bestHarvest(Game.getObjectById(creep.memory.bindResource));
                        }
                        return;
                    }
                    if (creep.room.memory.mode === EnumHarvestMode.HarvestAndTrans) {// not exist Butler
                        creep.bestTrans(findBuild(creep.room, STRUCTURE_SPAWN)[0]);
                        return;
                    }
                    if (creep.room.memory.mode === EnumHarvestMode.OnlyHarvest) {
                        creep.drop(RESOURCE_ENERGY);
                        creep.bestHarvest(Game.getObjectById(creep.memory.bindResource));
                        return;
                    }
                }
                //store is not have energy
                if (creep.memory.bindResource === undefined || Game.getObjectById(creep.memory.bindResource)===null) {
                    let harvestList = findRoleCreeps(EnumRole.Harvest, creep.room).filter(creep=>creep.ticksToLive>100);
                    let resourceList = creep.room.find(FIND_SOURCES);
                    if(harvestList.length===0) {
                        creep.memory.bindResource = resourceList[0].id;
                    }else{
                        for (let resource of resourceList) {
                            let canBind=true;
                            for (let harvest of harvestList) {
                                if(harvest.memory.bindResource===resource.id){
                                    canBind=false;
                                    break;
                                }
                            }
                            if(canBind){
                                creep.memory.bindResource=resource.id;
                                break;
                            }
                        }
                    }

                }
                let resource = Game.getObjectById(creep.memory.bindResource);
                if (resource&&resource.energy === 0) {
                    creep.bestMove(resource);
                    return;
                }
                creep.memory.behavior = EnumBehavior.Harvest;
            }
            break;
        }
        case EnumBehavior.Harvest:
            let bindResource = Game.getObjectById(creep.memory.bindResource);
            if(creep.pos.isNearTo(bindResource)){
                creep.bestMove(bindResource);
            }
            if(bindResource&&bindResource.energy>0){
                creep.bestHarvest(bindResource);
            }
            if (creep.usedStore()>creep.maxStore()*0.3) {//store have letter energy
                if (creep.memory.bindLink) {//exist bind link
                    let bindLink = Game.getObjectById(creep.memory.bindLink);
                    if (bindLink.freeStore() > 0) {//trans link
                        creep.bestTrans(bindLink);
                        creep.bestHarvest(Game.getObjectById(creep.memory.bindResource));
                    }
                }else{
                    if(creep.room.controller.level>=5){
                        let linkList=findLink(creep.room);
                        let closeLinkList = creep.pos.findInRange(linkList,3);
                        if(closeLinkList.length===1){
                            creep.memory.bindLink=closeLinkList[0].id;
                        }else if (closeLinkList.length>1){
                            let closeLink = creep.pos.findClosestByRange(closeLinkList);
                            creep.memory.bindLink=closeLink.id;
                        }
                    }
                }
            }
            if (creep.room.memory.mode===EnumHarvestMode.HarvestAndTrans && creep.freeStore() <=0) {
                creep.memory.behavior = EnumBehavior.Free;
            }
            break;
    }
}

//Butler
module.exports.butler = creep => {
    if(creep.memory.behavior===EnumBehavior.TransMineralToTerminal){
        if(creep.usedStore()>0){
            creep.bestTrans(creep.room.storage);
        }else{
            if(creep.room.terminal.freeStore()===0){
                creep.finishBehavior();
                return;
            }
            if(creep.freeStore()===creep.maxStore()){//can withdraw
                if(creep.memory.transMineralType===undefined){
                    creep.finishBehavior();
                    return;
                }
                let result=creep.bestWithdraw(creep.room.storage,creep.memory.transMineralType);
                if(result!==0&&result!==-9){
                    creep.finishBehavior();
                    return;
                }
            }else{
               let result=creep.bestTrans(creep.room.terminal,creep.memory.transMineralType);
               if(result===0){
                   creep.finishBehavior();
                   return;
               }
            }
        }
        return;
    }
    for (let resourceType in creep.store) {
        if(resourceType!==RESOURCE_ENERGY){
            if(creep.room.storage===undefined){
                creep.drop(resourceType);
            }else{
                creep.bestTrans(creep.room.storage,resourceType);
            }
            return;
        }
    }
    if(creep.memory.behavior===EnumBehavior.TransMineral){
        if(creep.usedStore()>0){
            creep.bestTrans(creep.room.storage);
        }else{
            let behaviorId = Game.getObjectById(creep.memory.behaviorId);
            let otherResource=RESOURCE_ENERGY;
            for (let resourceType in behaviorId.store) {
                if(resourceType!==RESOURCE_ENERGY){
                    otherResource=resourceType
                }
            }
            creep.bestWithdraw(behaviorId,otherResource);
            creep.finishBehavior();
        }
        return;
    }
    if(creep.memory.behavior===EnumBehavior.TransContainer){
        if(creep.usedStore()>0){
            let behavior=Game.getObjectById(creep.memory.behaviorId);
            if(behavior===null){
                creep.finishBehavior();
                return;
            }
            let result=creep.bestTrans(behavior);
            if(result===0){
                creep.finishBehavior();
                return;
            }
            if(behavior.freeStore()<=0){
                creep.finishBehavior();
                return;
            }
        }else{
            if(creep.room.storage.usedStore()<2000){
                creep.finishBehavior();
                return;
            }
            creep.bestWithdraw(creep.room.storage);
        }
        return;
    }

    //transLink other behavior
    if(creep.memory.behavior===EnumBehavior.TransLink){
        if (creep.usedStore()>0){
            if(creep.room.storage.freeStore()>0){
                creep.bestTrans(creep.room.storage);
                return;
            }
            if(creep.memory.replenishId===undefined){
                let freeStoreList=findEnergyStore(creep.room).filter(build=>build.freeStore()>0)
                creep.memory.replenishId=findBestClose(creep,freeStoreList)
            }
            creep.bestTrans(Game.getObjectById(creep.memory.replenishId));
            return;
        }
        let baseLink = Game.getObjectById(creep.memory.behaviorId);
        creep.bestWithdraw(baseLink);
        if(baseLink.usedStore()<=0){
            creep.finishBehavior();
        }
        return;
    }
    //execute replenish
    if(creep.memory.replenish!==EnumReplenish.Free&&creep.memory.replenish!==undefined){
        switch (creep.memory.replenish){
            case EnumReplenish.ReplenishEnergy:
                withDraw(creep);
                break;
            case EnumReplenish.PickEnergy:
                pickUp(creep)
                break;
        }
        return
    }
    //execute behavior meanwhile
    if(creep.memory.behaviorId){
        if(creep.usedStore()>0){//creep have energy
            switch (creep.memory.behavior) {
                case EnumBehavior.ReplenishBuild:
                    replenishBuild(creep);
                    break;
            }
        }else{
            //creep not energy
            replenishEnergy(creep);
        }
    }else{
        if(creep.freeStore()===0){
            toStop(creep);
        }else{
            replenishEnergy(creep);
        }
    }

}

//Engineer
function engine(creep){
    if(creep.memory.replenish){
        //execute replenish
        switch (creep.memory.replenish){
            case EnumReplenish.ReplenishEnergy:
                withDraw(creep);
                break;
            case EnumReplenish.PickEnergy:
                pickUp(creep)
                break;
            case EnumReplenish.WithDrawOtherCreep:
                carryOtherCreep(creep);
                break;
        }
        return;
    }
    //execute behavior
    if(creep.memory.behavior){
        if(creep.usedStore()>0) {//creep have energy
            switch (creep.memory.behavior) {
                case EnumBehavior.ReplenishBuild:
                    replenishBuild(creep);
                    break;
                case EnumBehavior.PickEnergy:
                    pickUp(creep);
                    break;
                case EnumBehavior.UpController:
                    up(creep);
                    break;
                case EnumBehavior.RepairBuild:
                    repair(creep);
                    break;
                case EnumBehavior.Building:
                    build(creep);
                    break;
            }
        }else{
            if(EnumBehavior.UpController){
                creep.finishBehavior();
            }
            replenishEnergy(creep);
        }
    }else{
        toStop(creep);
    }
}
module.exports.engine=engine;

//Defense
module.exports.defense = creep => {
    let invasionList = creep.room.find(FIND_HOSTILE_CREEPS);
    if (invasionList.length > 0) {
        let invasionCreep = creep.pos.findClosestByRange(invasionList);
        creep.bestAttack(invasionCreep)
    }
}

//OutHarvest autoBehavior is me
module.exports.outHarvest = creep => {
    if (creep.memory.workRoom === null) {//not bind workRoom,moveTo upRoot flags
        followFlagUpRoom(creep);
        return;
    }
    //bind workRoom
    if (creep.memory.bindResource === undefined) {
        //bind resource
        let outHarvestList = findRoleCreeps(EnumRole.OutHarvest, creep.room);
        let sourceList = creep.room.find(FIND_SOURCES);
        if (sourceList.length === 1) {//only one ,must bind
            creep.memory.bindResource = sourceList[0].id;
        } else {//average distribute resource
            let canBindResourceList = sourceList.filter(source => {
                let canBind = true;
                for (let harvest of outHarvestList) {
                    if (harvest.memory.bindResource === source.id) {
                        canBind = false
                    }
                }
                return canBind;
            });
            if (canBindResourceList.length > 0) {
                creep.memory.bindResource = canBindResourceList[0].id;
            } else {
                creep.memory.bindResource = sourceList[0].id;
            }

        }
    } else {//continued harvest
        let bindResource = Game.getObjectById(creep.memory.bindResource);
        creep.bestHarvest(bindResource);
    }
}

//OutEngineer autoBehavior is me
module.exports.outEngineer = creep => {
    if (creep.memory.workRoom === null) {//not bind workRoom,moveTo upRoot flags
        followFlagUpRoom(creep);
        return;
    }
    engine(creep);
}
//Occupy
module.exports.occupy = creep => {
    if (creep.memory.workRoom === null) {//not bind workRoom,moveTo upRoot flags
        followFlagUpRoom(creep);
        return;
    }
    if (creep.room.controller.my) {
        if (creep.signController(creep.room.controller, "✨BLACKJUNWIN!✨") === OK) {
            //create creep energy
            creep.suicide();
        }
    } else {
        let state = creep.claimController(creep.room.controller);
        if (state === ERR_NOT_IN_RANGE) {
            creep.bestMove(creep.room.controller);
        }
    }

}

module.exports.outTrans = creep => {
    if(creep.freeStore()===0){
        creep.memory.back=true;
    }
    let TransFlag = findFlagList(EnumFlag.Trans).filter(flag=>flag.room===undefined||flag.room.name!==creep.memory.createRoom)[0];
    //back
    if(creep.memory.back===true||TransFlag===null){
        if(creep.maxStore()!==creep.freeStore()){
            if(creep.room.name!==creep.memory.createRoom){
                const createRoomPos = new RoomPosition(25, 25, creep.memory.createRoom);
                return creep.bestOutMove(createRoomPos);
            }
            let resourceType;
            for (let storeKey in creep.store) {
                if(creep.usedStore(storeKey)>0){
                    resourceType = storeKey;
                    break;
                }
            }
            creep.bestTrans(creep.room.storage, resourceType);
            return ;
        }
        if(creep.ticksToLive<100){
            creep.suicide();
            return ;
        }
        creep.memory.back=undefined;
        return ;
    }
    //priority move to TransFlag
    if (TransFlag !== undefined && creep.memory.back===undefined) {
        if (!creep.spawning&&creep.freeStore() > 0) {//trans resource
            //is sample room
            if (TransFlag.room===undefined||creep.room.name !== TransFlag.room.name) {
               return creep.bestOutMove(TransFlag.pos);
            }
            //1.trans pos
            let fullStoreList = TransFlag.pos.lookFor(LOOK_STRUCTURES).filter(build => (build.structureType === STRUCTURE_STORAGE || build.structureType === STRUCTURE_CONTAINER));
            if (fullStoreList.length > 0) {
                let store = fullStoreList[0];
                let resourceType;
                for (let storeKey in store.store) {
                    if(Object.values(store.store).length>1&&storeKey===RESOURCE_ENERGY){
                        continue;
                    }
                    if (store.usedStore(storeKey) > 0) {
                        resourceType = storeKey;
                        break;
                    }
                }
                creep.bestWithdraw(store, resourceType);
                return;
            }
            //2.dropResource
            let dropResourceList = creep.room.find(FIND_DROPPED_RESOURCES).sort((a, b) => a.amount - b.amount);
            if (dropResourceList.length > 0) {
                creep.bestPickup(creep.pos.findClosestByRange(dropResourceList))
                return;
            }
        }
    }
}

module.exports.outWorker=creep=>{
    let removeFlag=findFlagList(EnumFlag.Remove).filter(flag=>flag.room===undefined||flag.room.name!==creep.memory.createRoom)[0];
    if (removeFlag !== undefined && removeFlag !== null) {
        if (removeFlag.room===undefined||creep.room.name !== removeFlag.room.name) {
            return  creep.bestOutMove(removeFlag.pos);
        }
        let removeList = removeFlag.pos.lookFor(LOOK_STRUCTURES);
        if(removeList.length>0){//dismantle build
            let removeItem=removeList[0];
            creep.bestDismantle(removeItem)
        }
    }
}

module.exports.attack=creep=>{
    let AttackFlag=findFlagList(EnumFlag.Attack).filter(flag=>flag.room===undefined||flag.room.name!==creep.memory.createRoom)[0];
    if (AttackFlag !== undefined && AttackFlag !== null) {
        if (AttackFlag.room===undefined||creep.room.name !== AttackFlag.room.name) {
            return  creep.bestOutMove(AttackFlag.pos);
        }
        let removeList = AttackFlag.pos.lookFor(LOOK_STRUCTURES);
        if(removeList.length>0){//attack build
            let removeItem=removeList[0];
            creep.bestAttack(removeItem);
            return ;
        }
        let towerList = creep.room.find(FIND_HOSTILE_STRUCTURES,{filter: build=>build.structureType===STRUCTURE_TOWER});
        if(towerList.length>0){
            creep.bestAttack(towerList[0]);
            return ;
        }
        let hostileCreepList = creep.room.find(FIND_HOSTILE_CREEPS);
        let healInvasionList=hostileCreepList.filter(creep=>{
            return creep.body.some(part=>part.type===HEAL)
        }).sort((a, b) => {
            const aHeals = a.body.filter(part => part.type === HEAL).length;
            const bHeals = b.body.filter(part => part.type === HEAL).length;
            return bHeals - aHeals;
        });
        if(hostileCreepList.length>0){
            if (healInvasionList.length>0){
                creep.bestAttack(healInvasionList[0]);
                return
            }
            creep.bestAttack(hostileCreepList[0]);
        }
    }
}